import Component from "../Component.js";
import Type from "../../experience/db/Type.js";

const Draw = ol.interaction.Draw;
const Stroke = ol.style.Stroke;
const Fill = ol.style.Fill;
const Style = ol.style.Style;
const CircleStyle = ol.style.Circle;
const Overlay = ol.Overlay;
const unByKey = ol.Observable.unByKey;

export default class Measure extends Component {
    constructor() {
        super();

        this.sketch = null;
        this.helpTooltipElement = null;
        this.helpTooltip = null;
        this.measureTooltipElement = null;
        this.measureTooltip = null;

        this.drawer.map.on('pointermove', this.pointerMoveHandler);
        this.drawer.map.getViewport().addEventListener('mouseout', () => {
            if (this.helpTooltipElement != null) {
                this.helpTooltipElement.classList.add('hidden');
            }
        });
    }

    createHelpTooltip() {
        if (this.helpTooltipElement) {
            this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
        }
        this.helpTooltipElement = document.createElement('div');
        this.helpTooltipElement.className = 'ol-tooltip hidden';
        this.helpTooltip = new Overlay({
            element: this.helpTooltipElement,
            offset: [15, 0],
            positioning: 'center-left',
        });
        this.drawer.map.addOverlay(this.helpTooltip);
    }

    createMeasureTooltip() {
        if (this.measureTooltipElement) {
            this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement);
        }
        this.measureTooltipElement = document.createElement('div');
        this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';
        this.measureTooltip = new Overlay({
            element: this.measureTooltipElement,
            offset: [0, -15],
            positioning: 'bottom-center',
            stopEvent: false,
            insertFirst: false,
        });
        this.drawer.map.addOverlay(this.measureTooltip);
    }

    pointerMoveHandler(evt) {
        if (evt.dragging) return;
        let helpMsg = '点击开始描画';
        if (this.sketch) { helpMsg = '点击继续描画'; }
        if (this.helpTooltipElement === undefined) return;
        this.helpTooltipElement.innerHTML = helpMsg;
        this.helpTooltip.setPosition(evt.coordinate);
        this.helpTooltipElement.classList.remove('hidden');
    }

    formatLength(line) {
        let length = 0;
        const points = line.flatCoordinates;
        for (let i = 0; i < points.length - 2; i = i + 2) {
            const x1 = this.algo.denormalX(points[i]);
            const y1 = this.algo.denormalY(points[i + 1]);
            const x2 = this.algo.denormalX(points[i+2]);
            const y2 = this.algo.denormalY(points[i + 3]);
            length += this.algo.distance(x1, y1, x2, y2);
        }

        return length.toFixed(2) + 'm';
    };

    addInteraction() {
        const self = this;
        const draw = new Draw({
            source: this.drawer.source(Type.Measure),
            type: 'LineString',
            style: new Style({
                fill: new Fill({
                    color: 'rgba(255, 255, 255, 0.2)',
                }),
                stroke: new Stroke({
                    color: 'rgba(255, 0, 0, 0.5)',
                    lineDash: [10, 10],
                    width: 2,
                }),
                image: new CircleStyle({
                    radius: 3,
                    stroke: new Stroke({
                        color: 'rgba(255, 0, 0, 0.7)',
                    }),
                    fill: new Fill({
                        color: 'rgba(255, 255, 255, 1)',
                    }),
                }),
            }),
        });
        this.drawer.map.addInteraction(draw);

        this.createMeasureTooltip();
        this.createHelpTooltip();

        let listener;
        draw.on('drawstart', function (evt) {
            this.sketch = evt.feature;
            let tooltipCoord = evt.coordinate;
            listener = this.sketch.getGeometry().on('change', function (evt) {
                const geom = evt.target;
                tooltipCoord = geom.getLastCoordinate();
                self.measureTooltipElement.innerHTML = self.formatLength(geom);
                self.measureTooltip.setPosition(tooltipCoord);
            });
        });

        draw.on('drawend', function () {
            self.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static';
            self.measureTooltip.setOffset([0, -7]);
            self.sketch = null;
            self.measureTooltipElement = null;
            self.createMeasureTooltip();
            unByKey(listener);
            self.drawer.map.removeInteraction(draw);
        });

        window.onkeydown = function(event) {
            if (event.defaultPrevented) return;
            let handled = false;
            if (event.key === "Escape") {
                self.drawer.source(Type.Measure).clear();
                self.drawer.map.removeInteraction(draw);
                self.$$(".ol-tooltip").hide();
                window.onkeydown = null;
                self.toast("距离测量功能被手动取消。");
            }
            if (handled) event.preventDefault();
        }
    }

    template() {
        const measureButton = `<div id="measure"  class="GisUtilIcon" style="position: absolute;top: 150px;left: 25px;z-index: 999"><i class="fas fa-ruler"></i></div>`
        this.$$("body").append(measureButton);
    }

    control() {
        this.$$("#measure").on("click", () => {
            this.toast("开启距离测量,点击'ESC'取消");
            this.addInteraction();
        });
    }
}